<?php
/**
 * 自定义的模型基类
 */
declare(strict_types=1);

namespace App\Model;

use Hyperf\Database\Model\Builder;
use Hyperf\Utils\ApplicationContext;
use Psr\SimpleCache\CacheInterface;
use Psr\SimpleCache\InvalidArgumentException;

abstract class MyBaseModel extends Model
{
    /**
     * 查询缓存
     * @param Builder $builder
     * @param int $ttl
     * @param int $emptyTtl
     * @param string $cacheKey
     * @return array
     */
    public static function getModelsByBuilderFromCache(
        Builder $builder,
        int $ttl = 3600,
        int $emptyTtl = 600,
        string $cacheKey = ''
    ): array {
        if (!$cacheKey) {
            $cacheKey = static::getCacheKeyByBuilder($builder);
        }
        try {
            $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
            $models = $cache->get($cacheKey);
            if (!is_null($models)) {
                return $models;
            }
            $models = $builder->getModels();
            $cache->set($cacheKey, $models, $models ? $ttl : $emptyTtl);
            return $models;
        } catch (InvalidArgumentException $e) {
            return [];
        }
    }

    /**
     * 生成缓存Key
     * @param Builder $builder
     * @return string
     */
    private static function getCacheKeyByBuilder(Builder $builder): string
    {
        $connectionName = $builder->getModel()->getConnectionName();
        $sql = $builder->toSql();
        $bindings = $builder->getBindings();
        return 'models_cache:' . $connectionName . ':' . md5($sql . '_' . json_encode($bindings));
    }

    /**
     * 查询缓存(IDS)
     * @param Builder $builder
     * @param int $ttl
     * @param int $emptyTtl
     * @param string $cacheKey
     * @return array
     */
    public static function getIdsByBuilderFromCache(
        Builder $builder,
        int $ttl = 3600,
        int $emptyTtl = 600,
        string $cacheKey = ''
    ): array {
        if (!$cacheKey) {
            $cacheKey = static::getCacheKeyByBuilder($builder);
        }
        try {
            $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
            $ids = $cache->get($cacheKey);
            if (is_array($ids)) {
                return $ids;
            }
            $ids = [];
            $idName = $builder->getModel()->getKeyName();
            $models = $builder->getModels();
            foreach ($models as $model) {
                array_push($ids, $model->{$idName});
            }
            $cache->set($cacheKey, $ids, $ids ? $ttl : $emptyTtl);
            return $ids;
        } catch (InvalidArgumentException $e) {
            return [];
        }
    }

    /**
     * 计数缓存
     * @param Builder $builder
     * @param int $ttl
     * @param int $emptyTtl
     * @param string $cacheKey
     * @return int
     */
    public static function getCountByBuilderFromCache(
        Builder $builder,
        int $ttl = 3600,
        int $emptyTtl = 600,
        string $cacheKey = ''
    ): int {
        if (!$cacheKey) {
            $cacheKey = static::getCacheKeyByBuilder($builder);
        }
        try {
            $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
            $count = $cache->get($cacheKey);
            if (is_int($count)) {
                return $count;
            }
            $count = $builder->count();
            $cache->set($cacheKey, $count, $count ? $ttl : $emptyTtl);
            return $count;
        } catch (InvalidArgumentException $e) {
            return 0;
        }
    }
}
